home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Applications / NIH Image 1.55 / Source / Camera.p < prev    next >
Encoding:
Text File  |  1994-03-22  |  34.8 KB  |  1,294 lines  |  [TEXT/PJMM]

  1. unit Camera;
  2.  
  3. {Routines used by the NIH Image for supporting the Data Translation}
  4. {QuickCapture card, the Scion Image 1000, and the Scion LG-3.}
  5.  
  6. interface
  7.  
  8.  
  9.     uses
  10.         QuickDraw, Palettes, PrintTraps, globals, Utilities, Graphics, File1, Analysis;
  11.  
  12.  
  13.     procedure AverageFrames;
  14.     procedure GetFrame;
  15.     procedure CaptureAndDisplayFrame;
  16.     procedure HighlightPixels;
  17.     procedure ShowTriggerMessage;
  18.     procedure StartDigitizing;
  19.     procedure StopDigitizing;
  20.     procedure SetVideoChannel;
  21.     function GetFGPixel (h, v: integer): integer;
  22.     procedure CopyOffscreen (src, dst: PixMapHandle; sRect, dRect: rect);
  23.     procedure GetScionFrame (DisplayPoint: point);
  24.     procedure WaitForTrigger;
  25.     procedure ShowChannel;
  26.     procedure ShowVideoControl;
  27.     procedure UpdateVideoControl;
  28.     procedure DoVideoControl (item: integer);
  29.  
  30.  
  31.  
  32. implementation
  33.  
  34.     type
  35.         IntPtr = ^integer;
  36.  
  37.     var
  38.         SavePicBaseAddr: ptr;
  39.         StopFlagLoc: IntPtr;
  40.  
  41.  
  42.     procedure CorrectShadingOfLine (PicPtr, BFPtr: ptr; width, BFMean: integer);
  43. {}
  44. {VAR}
  45. {  PicLine,BFLine:LinePtr;}
  46. {  i,value:integer;}
  47. {BEGIN}
  48. {  PicLine:=LinePtr(PicPtr);}
  49. {  BFLine:=LinePtr(BFPtr);}
  50. {  FOR i:=0 TO width-1 DO BEGIN}
  51. {    value:=PicLine^[i];}
  52. {    value:=255-value;}
  53. {    value:=(LongInt(value)*BFMean+(BFLine^[i] DIV 2)) DIV BFLine^[i];}
  54. {    IF value>254 THEN value:=254;}
  55. {    IF value<1 THEN value:=1;}
  56. {    PicLine^[i]:=255-value;}
  57. {  END;}
  58. {  }
  59.   {a0=data pointer}
  60.   {a1=blank field data pointer}
  61.   {d0=count}
  62.   {d1=pixel value}
  63.   {d2=blank field pixel value}
  64.   {d3=blank field mean}
  65.   {d4=temp}
  66.   {d5=max pixel value(245)}
  67.   {d6=min pixel value(1)}
  68.     inline
  69.         $4E56, $0000, {   link    a6,#0}
  70.         $48E7, $FEC0, {   movem.l    a0-a1/d0-d6,-(sp)}
  71.         $206E, $000C, {   move.l    12(a6),a0}
  72.         $226E, $0008, {   move.l    8(a6),a1}
  73.         $4280,       {   clr.l    d0}
  74.         $302E, $0006, {   move.w    6(a6),d0}
  75.         $362E, $0004, {   move.w    4(a6),d3}
  76.         $2A3C, $0000, $00FE, {   move.l    #254,d5}
  77.         $2C3C, $0000, $0001, {   move.l    #1,d6}
  78.         $5380,       {   subq.l    #1,d0}
  79.         $4281,       {   clr.l    d1}
  80.         $4282,       {   clr.l    d2}
  81.         $1210,       {L1    move.b    (a0),d1}
  82.         $1419,       {   move.b    (a1)+,d2}
  83.         $4601,       {   not.b    d1}
  84.         $C2C3,       {   mulu.w    d3,d1}
  85.         $2802,       {   move.l    d2,d4}
  86.         $E244,       {   asr.w    #1,d4}
  87.         $D284,       {   add.l    d4,d1}
  88.         $82C2,       {   divu.w    d2,d1}
  89.         $B245,       {   cmp.w    d5,d1}
  90.         $6F02,       {   ble.s    L2}
  91.         $3205,       {   move.w    d5,d1}
  92.         $B246,       {L2    cmp.w    d6,d1}
  93.         $6C02,       {   bge.s    L3}
  94.         $3206,       {   move.w    d6,d1}
  95.         $4601,       {L3    not.b    d1}
  96.         $10C1,       {   move.b    d1,(a0)+}
  97.         $51C8, $FFDE, {   dbra    d0,L1}
  98.         $4CDF, $037F, {   movem.l    (sp)+,a0-a1/d0-d6}
  99.         $4E5E,       {   unlk    a6}
  100.         $DEFC, $000C; {   add.w    #12,sp}
  101. {END;}
  102.  
  103.  
  104.     procedure CorrectShading;
  105.         var
  106.             i: integer;
  107.             offset: LongInt;
  108.             p1, p2: ptr;
  109.             str: str255;
  110.     begin
  111.         with info^ do begin
  112.                 if ImageSize <> BlankFieldInfo^.ImageSize then begin
  113.                         beep;
  114.                         exit(CorrectShading);
  115.                     end;
  116.                 ShowWatch;
  117.                 p1 := PicBaseAddr;
  118.                 p2 := BlankFieldInfo^.PicBaseAddr;
  119.                 for i := 1 to nLines do begin
  120.                         CorrectShadingOfLine(p1, p2, PixelsPerLine, BlankFieldMean);
  121.                         p1 := ptr(ord4(p1) + info^.BytesPerRow);
  122.                         p2 := ptr(ord4(p2) + BlankFieldInfo^.BytesPerRow);
  123.                         if i mod 96 = 0 then
  124.                             UpdatePicWindow;
  125.                     end;
  126.                 UpdatePicWindow;
  127.                 str := title;
  128.                 if SpatiallyCalibrated then
  129.                     str := concat(str, chr($13)); {Black Diamond}
  130.                 if DensityCalibrated then
  131.                     str := concat(str, '');
  132.                 if wptr <> nil then
  133.                     SetWTitle(wptr, concat(str, '(Corrected)'));
  134.             end;
  135.     end;
  136.  
  137.  
  138.     procedure CopyOffscreen (src, dst: PixMapHandle; sRect, dRect: rect);
  139.         var
  140.             SaveGDevice: GDHandle;
  141.     begin
  142.         SaveGDevice := GetGDevice;
  143.         SetGDevice(osGDevice);
  144.         hlock(handle(src));
  145.         hlock(handle(dst));
  146.         CopyBits(BitMapHandle(src)^^, BitMapHandle(dst)^^, sRect, dRect, SrcCopy, nil);
  147.         hunlock(handle(src));
  148.         hunlock(handle(dst));
  149.         SetGDevice(SaveGDevice);
  150.     end;
  151.  
  152.  
  153.     procedure StopDigitizing;
  154.     begin
  155.         if digitizing then
  156.             with info^ do begin
  157.                     ShowFrameRate('', fgStartTicks, fgFrameCount);
  158.                     CopyOffscreen(fgPort^.portPixMap, osPort^.portPixMap, PicRect, PicRect);
  159.                     SetItem(SpecialMenuH, StartItem, 'Start Capturing');
  160.                     Digitizing := false;
  161.                     ContinuousHistogram := false;
  162.                     with info^ do
  163.                         if PictureType = FrameGrabberType then begin
  164.                                 title := 'Camera';
  165.                                 UpdateTitleBar;
  166.                                 if HighlightSaturatedPixels then
  167.                                     LoadLUT(ctable);
  168.                             end;
  169.                     if (BlankFieldInfo <> nil) and not OptionKeyDown then
  170.                         CorrectShading;
  171.                 end;
  172.     end;
  173.  
  174.  
  175.     procedure GetFrame;
  176.         var
  177.             ticks, timeout: LongInt;
  178.     begin
  179.         if FrameGrabber = ScionLG3 then begin
  180.                 if ExternalTrigger then begin {Wait for trigger}
  181.                         ControlReg^ := $90;
  182.                         repeat
  183.                             if button then
  184.                                 ExternalTrigger := false;
  185.                         until (BitAnd(ControlReg^, $80) = $80) or not ExternalTrigger;
  186.                         ControlReg^ := 0;
  187.                         if Digitizing then
  188.                             StopDigitizing;
  189.                         UpdateVideoControl;
  190.                     end {if External Trigger}
  191.                 else begin
  192.                         TimeOut := TickCount + 30;  {1/2sec. timeout}
  193.                         ControlReg^ := $80; {Start frame capture}
  194.                         while BitAnd(ControlReg^, $80) = 0 do begin    {Wait for it to complete}
  195.                                 if TickCount > TimeOut then begin
  196.                                         ControlReg^ := 0;
  197.                                         leave
  198.                                     end;
  199.                             end;
  200.                         ControlReg^ := 0;
  201.                     end;
  202.             end
  203.         else begin {QuickCapture}
  204.                 if ExternalTrigger then begin {Wait for trigger}
  205.                         ControlReg^ := BitAnd($82, 255);
  206.                         repeat
  207.                             if button then
  208.                                 ExternalTrigger := false;
  209.                         until (ControlReg^ >= 0) or not ExternalTrigger;
  210.                         if Digitizing then
  211.                             StopDigitizing;
  212.                         UpdateVideoControl;
  213.                     end {if External Trigger}
  214.                 else begin
  215.                         TimeOut := TickCount + 30;  {1/2sec. timeout}
  216.                         ControlReg^ := BitAnd($80, 255); {Start frame capture}
  217.                         while ControlReg^ < 0 do begin    {Wait for it to complete}
  218.                                 if TickCount > TimeOut then
  219.                                     leave
  220.                             end;
  221.                     end;
  222.             end; {QuickCapture}
  223.         fgFrameCount := fgFrameCount + 1;
  224.     end;
  225.  
  226.  
  227.     procedure CaptureAndDisplayFrame;
  228.         var
  229.             tPort: GrafPtr;
  230.     begin
  231.         with info^ do begin
  232.                 if (PictureType <> FrameGrabberType) or (PixelsPerLine <> fgWidth) or (nlines <> fgHeight) then begin
  233.                         Digitizing := false;
  234.                         exit(CaptureAndDisplayFrame);
  235.                     end;
  236.                 GetFrame;
  237.                 getPort(tPort);
  238.                 SetPort(wptr);
  239.                 hlock(handle(fgPort^.portPixMap));
  240.                 hlock(handle(CGrafPort(wptr^).PortPixMap));
  241.                 CopyBits(BitMapHandle(fgPort^.portPixMap)^^, BitMapHandle(CGrafPort(wptr^).PortPixMap)^^, SrcRect, wrect, gCopyMode, nil);
  242.                 hunlock(handle(fgPort^.portPixMap));
  243.                 hunlock(handle(CGrafPort(wptr^).PortPixMap));
  244.                 SetPort(tPort);
  245.             end;
  246.     end;
  247.  
  248.  
  249.     procedure SetReg (index, value: integer);
  250.         const
  251.             RegOffset = $f5fe0;
  252.         var
  253.             reg: ptr;
  254.     begin
  255.         reg := ptr(fgSlotBase + RegOffset + index * 4);
  256.         reg^ := value;
  257.     end;
  258.  
  259.  
  260.     procedure ResetScion (GrabRect: rect; DisplayPoint: point);
  261.         const
  262.             ilutOffset = $f0000;
  263.             LineStartsRamOffset = $f4000;
  264.         type
  265.             LineStartsArray = packed array[0..8191] of UnsignedByte;
  266.             LineStartsType = ^LineStartsArray;
  267.         var
  268.             ScreenRowBytesx2: LongInt;
  269.             LutPtr: ptr;
  270.             LineStarts: LineStartsType;
  271.             EvenStart, OddStart: LongInt;
  272.             width, height, IndexOdd, IndexEven, index, i: integer;
  273.             hstart, vstart: integer;
  274.     begin
  275.         ScreenRowBytesx2 := ScreenRowBytes * 2;
  276.         LoadInputLUT(Ptr(fgSlotBase + ilutOffset));
  277.         with GrabRect, DisplayPoint do begin
  278.                 hstart := BitAnd(left, $fffc);
  279.                 vstart := BitAnd(top, $fffe);
  280.                 width := right - left;
  281.                 height := bottom - top;
  282.                 StopFlagLoc := IntPtr(LongInt(ScreenBase) + h + ScreenRowBytes * (v + height - 2) + 4);
  283.                 EvenStart := LongInt(ScreenBase) + h + ScreenRowBytes * v;
  284.                 OddStart := EvenStart + ScreenRowBytes;
  285.                 IndexOdd := 0;
  286.                 IndexEven := (height div 2) * 16;
  287.             end;
  288.         LineStarts := LineStartsType(fgSlotBase + LineStartsRamOffset);
  289.         for i := 1 to height div 2 do begin
  290.                 LineStarts^[IndexOdd] := BSR(BitAnd(OddStart, $ff000000), 24);
  291.                 LineStarts^[IndexOdd + 4] := BSR(BitAnd(OddStart, $ff0000), 16);
  292.                 LineStarts^[IndexOdd + 8] := BSR(BitAnd(OddStart, $ff00), 8);
  293.                 LineStarts^[IndexOdd + 12] := BitAnd(OddStart, $fc);
  294.                 LineStarts^[IndexEven] := BSR(BitAnd(EvenStart, $ff000000), 24);
  295.                 LineStarts^[IndexEven + 4] := BSR(BitAnd(EvenStart, $ff0000), 16);
  296.                 LineStarts^[IndexEven + 8] := BSR(BitAnd(EvenStart, $ff00), 8);
  297.                 LineStarts^[IndexEven + 12] := BitAnd(EvenStart, $fc);
  298.                 IndexOdd := IndexOdd + 16;
  299.                 IndexEven := IndexEven + 16;
  300.                 OddStart := OddStart + ScreenRowBytesx2;
  301.                 EvenStart := EvenStart + ScreenRowBytesx2;
  302.             end;
  303.         Index := height * 16;
  304.         LineStarts^[Index] := 0;
  305.         LineStarts^[Index + 4] := 0;
  306.         LineStarts^[Index + 8] := 0;
  307.         LineStarts^[Index + 12] := 1;
  308.         SetReg(1, 0);
  309.         SetReg(2, 162 - (width div 4));
  310.         SetReg(3, 0);
  311.         SetReg(4, 225 - (hstart div 4));
  312.         SetReg(5, 255 - (width div 4));
  313.         SetReg(6, 241 - (vstart div 2));
  314.         SetReg(7, 255 - (height div 2));
  315.     end;
  316.  
  317.  
  318.     procedure GetScionFrame (DisplayPoint: point);
  319.   {Captures a single Scion frame to screen memory.}
  320.         type
  321.             IntPtr = ^integer;
  322.         var
  323.             FlagLoc: IntPtr;
  324.             StartTime: LongInt;
  325.             myMMUMode: signedbyte;
  326.     begin
  327.         with DisplayPoint do
  328.             FlagLoc := IntPtr(LongInt(ScreenBase) + h + ScreenRowBytes * v + 4);
  329.         StartTime := TickCount;
  330.         myMMUMode := 1;
  331.         SwapMMUMode(myMMUMode);
  332.         FlagLoc^ := $00ff;
  333.         SetReg(1, BitOr(128, VideoChannel * 4)); {Grab Enable}
  334.         while FlagLoc^ = $00ff do
  335.             if TickCount > (StartTime + 5) then begin
  336.                     SetReg(1, 0); {Stop Grabbing}
  337.                     SwapMMUMode(myMMUMode);
  338.                     exit(GetScionFrame)
  339.                 end;
  340.         StopFlagLoc^ := $00ff;
  341.         while StopFlagLoc^ = $00ff do begin
  342.             end;
  343.         SetReg(1, 0); {Stop Grabbing}
  344.         SwapMMUMode(myMMUMode);
  345.     end;
  346.  
  347.  
  348.     function GetScreenPixel (h, v: integer): integer;
  349.         var
  350.             offset: LongInt;
  351.             p: ptr;
  352.     begin
  353.         offset := LongInt(v) * ScreenRowBytes + h;
  354.         p := ptr(ord4(ScreenBase) + offset);
  355.         GetScreenPixel := BAND(p^, 255);
  356.     end;
  357.  
  358.  
  359.     procedure CopyScionFrameOffscreen (DisplayPoint: point; wwidth, wheight: integer);
  360.         var
  361.             src, dst: ptr;
  362.             line: integer;
  363.     begin
  364.         with Info^ do begin
  365.                 with DisplayPoint do
  366.                     src := ptr(LongInt(ScreenBase) + h + ScreenRowBytes * v);
  367.                 dst := ptr(LongInt(PicBaseAddr));
  368.                 for line := 1 to wheight do begin
  369.                         BlockMove(src, dst, wwidth);
  370.                         src := ptr(ord4(src) + ScreenRowBytes);
  371.                         dst := ptr(ord4(dst) + BytesPerRow);
  372.                     end;
  373.             end;
  374.     end;
  375.  
  376.  
  377.     procedure DoMiniEventLoop (FullScreenMode: boolean);
  378.         var
  379.             loc: point;
  380.             event: EventRecord;
  381.     begin
  382.         FlushEvents(EveryEvent, 0);
  383.         if not FullScreenMode then
  384.             DrawLabels('X:', 'Y:', 'Value:');
  385.         repeat
  386.             GetMouse(loc);
  387.             LocalToGlobal(loc);
  388.             if not FullScreenMode then
  389.                 with loc do
  390.                     Show3Values(h, v, GetScreenPixel(h, v));
  391.         until WaitNextEvent(mDownMask + KeyDownMask, Event, 0, nil);
  392.     end;
  393.  
  394.  
  395.     procedure SelectCameraWindow (grabber: PicType);
  396.   {If there is a Camera window, activate it, otherwise, do nothing.}
  397.         var
  398.             i: integer;
  399.             TempInfo: InfoPtr;
  400.     begin
  401.         for i := 1 to nPics do begin
  402.                 TempInfo := pointer(WindowPeek(PicWindow[i])^.RefCon);
  403.                 if grabber = TempInfo^.PictureType then begin
  404.                         if PicWindow[i] <> nil then begin
  405.                                 if OpPending then
  406.                                     KillRoi;
  407.                                 SelectWindow(PicWindow[i]);
  408.                                 Info := TempInfo;
  409.                                 ActivateWindow;
  410.                             end; {if}
  411.                         leave;
  412.                     end; {if}
  413.             end; {for}
  414.     end;
  415.  
  416.  
  417.     procedure CaptureUsingScion;
  418.         var
  419.             GrabRect, ScreenSrcRect: rect;
  420.             DisplayPoint: point;
  421.             FullScreenMode: boolean;
  422.             wwidth, wheight: integer;
  423.             tPort: GrafPtr;
  424.             SaveBackgroundColor, hstart, vstart: integer;
  425.             ignore: integer;
  426.             mloc: point;
  427.             MainDevice: GDHandle;
  428.             SrcPixMap: PixMapHandle;
  429.             myMMUMode: signedbyte;
  430.             FlagLoc: IntPtr;
  431.             StartTime: LongInt;
  432.             grabbing: boolean;
  433.     begin
  434.         FullScreenMode := OptionKeyDown and (ScreenWidth = 640);
  435.         if FullScreenMode or (ScreenWidth > 640) then begin
  436.                 wwidth := MaxScionWidth;
  437.                 wheight := 480
  438.             end
  439.         else begin
  440.                 wwidth := 552;
  441.                 if wwidth > MaxScionWidth then
  442.                     wwidth := MaxScionWidth;
  443.                 wheight := 436;
  444.             end;
  445.         SelectCameraWindow(ScionType);
  446.         with Info^ do
  447.             if PictureType = ScionType then
  448.                 with wrect do
  449.                     if (wwidth <> right) or (wheight <> bottom) then begin
  450.                             changes := false;
  451.                             ignore := CloseAWindow(wptr);
  452.                         end;
  453.         with info^ do
  454.             if PictureType <> ScionType then begin
  455.                     if not NewPicWindow('Camera(Scion)', wwidth, wheight) then begin
  456.                             beep;
  457.                             exit(CaptureUsingScion)
  458.                         end;
  459.                 end;
  460.         KillRoi;
  461.         with info^ do begin
  462.                 PictureType := ScionType;
  463.                 changes := true;
  464.                 UpdateTitleBar;
  465.             end;
  466.         hstart := (640 - wwidth) div 2;
  467.         vstart := (480 - wheight) div 2;
  468.         SetRect(GrabRect, hstart, vstart, hstart + wwidth, vstart + wheight);
  469.         if FullScreenMode then
  470.             with DisplayPoint do begin
  471.                     h := BitAnd((640 - wwidth) div 2, $fffc);
  472.                     v := 0;
  473.                 end
  474.         else
  475.             with DisplayPoint do begin
  476.                     h := PicLeftBase;
  477.                     v := PicTopBase;
  478.                 end;
  479.         ResetScion(GrabRect, DisplayPoint);
  480.         if FullScreenMode then begin
  481.                 GetPort(tPort);
  482.                 SaveBackgroundColor := BackgroundIndex;
  483.                 SetBackgroundColor(BlackIndex);
  484.                 EraseScreen;
  485.             end;
  486.         if info^.magnification <> 1.0 then
  487.             Unzoom;
  488.         with DisplayPoint do
  489.             FlagLoc := IntPtr(LongInt(ScreenBase) + h + ScreenRowBytes * v + 4);
  490.         StartTime := TickCount;
  491.         grabbing := true;
  492.         myMMUMode := 1;
  493.         SwapMMUMode(myMMUMode);
  494.         FlagLoc^ := $00ff;
  495.         SetReg(1, BitOr(128, VideoChannel * 4)); {Grab Enable}
  496.         while FlagLoc^ = $00ff do
  497.             if TickCount > (StartTime + 5) then begin
  498.                     SetReg(1, 0); {Stop Grabbing}
  499.                     FlagLoc^ := $0000;
  500.                     SwapMMUMode(myMMUMode);
  501.                     grabbing := false;
  502.                 end;
  503.         if grabbing then begin
  504.                 SwapMMUMode(myMMUMode);
  505.                 DoMiniEventLoop(FullScreenMode);
  506.                 myMMUMode := 1;
  507.                 SwapMMUMode(myMMUMode);
  508.                 StopFlagLoc^ := $00ff;
  509.                 while StopFlagLoc^ = $00ff do begin
  510.                     end;
  511.                 SetReg(1, 0);   {Stop Grabbing}
  512.                 SwapMMUMode(myMMUMode);
  513.                 HideCursor;
  514.                 GetScionFrame(DisplayPoint);
  515.             end;
  516.         MainDevice := GetMainDevice;
  517.         SrcPixMap := MainDevice^^.gdPMap;
  518.         with DisplayPoint, ScreenSrcRect do begin
  519.                 left := h;
  520.                 top := v;
  521.                 right := left + wwidth;
  522.                 bottom := top + wheight;
  523.             end;
  524.         with info^ do begin
  525.                 CopyOffscreen(SrcPixMap, osPort^.portPixMap, ScreenSrcRect, PicRect);
  526.                 ShowCursor;
  527.                 if FullScreenMode then begin
  528.                         RestoreScreen;
  529.                         SetBackgroundColor(SaveBackgroundColor);
  530.                         SetPort(tPort);
  531.                     end;
  532.                 title := 'Camera';
  533.                 UpdateTitleBar;
  534.             end; {with}
  535.         if (BlankFieldInfo <> nil) and not OptionKeyDown then
  536.             CorrectShading;
  537.         FlushEvents(EveryEvent, 0);
  538.     end;
  539.  
  540.  
  541.     procedure HighlightPixels;
  542.         var
  543.             lut: MyCSpecArray;
  544.     begin
  545.         with info^ do begin
  546.                 lut := ctable;
  547.                 lut[1].rgb := Highlight1;
  548.                 lut[254].rgb := Highlight254;
  549.                 LoadLUT(lut);
  550.             end;
  551.     end;
  552.  
  553.  
  554.     procedure ShowTriggerMessage;
  555.     begin
  556.         if ExternalTrigger and ((FrameGrabber = QuickCapture) or (FrameGrabber = ScionLG3)) then
  557.             ShowMessage(concat('EXTERNAL TRIGGER MODE', cr, '(Press mouse button to exit)'));
  558.     end;
  559.  
  560.  
  561.     procedure StartDigitizing;
  562.         var
  563.             i, width, height: integer;
  564.             trect: rect;
  565.             NewWindow: boolean;
  566.     begin
  567.         if FrameGrabber = Scion then begin
  568.                 if HighlightSaturatedPixels then
  569.                     HighlightPixels;
  570.                 CaptureUsingScion;
  571.                 if HighlightSaturatedPixels then
  572.                     LoadLUT(info^.ctable);
  573.                 exit(StartDigitizing)
  574.             end;
  575.         if Digitizing then begin
  576.                 StopDigitizing;
  577.                 if BlankFieldInfo <> nil then
  578.                     wait(15);
  579.                 FlushEvents(EveryEvent, 0); {In case user holds key down too long}
  580.                 exit(StartDigitizing)
  581.             end;
  582.         if FrameGrabber = NoFrameGrabber then begin
  583.                 PutMessage('Capturing requires a Data Translation or SCION frame grabber card.');
  584.                 exit(StartDigitizing)
  585.             end;
  586.         if info^.PictureType <> FrameGrabberType then
  587.             SelectCameraWindow(FrameGrabberType);
  588.         NewWindow := false;
  589.         with info^ do
  590.             if (PictureType <> FrameGrabberType) or (PixelsPerLine <> fgWidth) or (nlines <> fgHeight) then begin
  591.                     if not NewPicWindow('Camera', fgWidth, fgHeight) then
  592.                         exit(StartDigitizing);
  593.                     NewWindow := true;
  594.                 end;
  595.         with info^ do begin
  596.                 PictureType := FrameGrabberType;
  597.                 if NewWindow and (not EqualRect(SrcRect, PicRect)) then {Center Frame}
  598.                     with SrcRect do begin
  599.                             width := right - left;
  600.                             height := bottom - top;
  601.                             left := (PicRect.right - width) div 2;
  602.                             right := left + width;
  603.                             top := (PicRect.bottom - height) div 2;
  604.                             bottom := top + height;
  605.                         end;
  606.                 KillRoi;
  607.                 if ScaleToFitWindow then
  608.                     ScaleToFit;
  609.                 with SrcRect do begin
  610.                         width := right - left;
  611.                         left := band(left, $fffc);
  612.                         right := left + width;
  613.                     end;
  614.                 GetWindowRect(wptr, trect);
  615.                 with trect do
  616.                     if band(left, 3) <> 0 then
  617.                         MoveWindow(wptr, band(left, $fffc), top, true); {Forces window to be word aligned}
  618.                 with SrcRect do {Prevents bus errors when Camera window moved.}
  619.                     if (top = 0) and (bottom < PicRect.bottom) then begin
  620.                             top := top + 1;
  621.                             bottom := bottom + 1;
  622.                         end;
  623.                 ResetFrameGrabber;
  624.                 Digitizing := true;
  625.                 SetItem(SpecialMenuH, StartItem, 'Stop Capturing');
  626.                 changes := true;
  627.                 BinaryPic := false;
  628.                 UpdateTitleBar;
  629.                 if HighlightSaturatedPixels then
  630.                     HighlightPixels;
  631.             end; {with info}
  632.         fgFrameCount := 0;
  633.         fgStartTicks := TickCount;
  634.         ContinuousHistogram := false;
  635.         ShowTriggerMessage;
  636.     end;
  637.  
  638.  
  639.     procedure AddLineToSum (src, dst: ptr; width: LongInt);
  640. {$IFC false}
  641.         type
  642.             SumLineType = array[0..2047] of integer;
  643.             fptr = ^SumLineType;
  644.         var
  645.             FrameLine: LinePtr;
  646.             SumLine: fptr;
  647.             i: integer;
  648.     begin
  649.         FrameLine := LinePtr(src);
  650.         SumLine := fptr(dst);
  651.         for i := 0 to width - 1 do
  652.             SumLine^[i] := SumLine^[i] + FrameLine^[i];
  653.     end;
  654. {$ENDC}
  655. inline
  656. {a0=data pointer}
  657. {a1=sum buffer pointer}
  658. {d0=count}
  659. {d1=pixel value}
  660. {d2=temp}
  661.     $4E56, $0000, {link    a6,#0}
  662.     $48E7, $E0C0, {movem.l    a0-a1/d0-d2,-(sp)}
  663.     $206E, $000C, {move.l    12(a6),a0}
  664.     $226E, $0008, {move.l    8(a6),a1}
  665.     $202E, $0004, {move.l    4(a6),d0}
  666.     $5380,              {subq.l    #1,d0}
  667.     $4281,              {clr.l    d1}
  668.     $4282,              {clr.l    d2}
  669.     $1218,              {L1    move.b    (a0)+,d1}
  670.     $3411,              {move.w    (a1),d2}
  671.     $D441,              {add.w      d1,d2}
  672.     $32C2,              {move.w    d2,(a1)+}
  673.     $51C8, $FFF6, {dbra    d0,L1}
  674.     $4CDF, $0307, {movem.l    (sp)+,a0-a1/d0-d2}
  675.     $4E5E,               {unlk    a6}
  676.     $DEFC, $000C; {add.w    #12,sp}
  677.  
  678.  
  679.  
  680. function DoAveragingOptions: boolean;
  681.     const
  682.         FramesID = 8;
  683.         VideoRateID = 9;
  684.         SumID = 10;
  685.         ShowID = 11;
  686.         FixID = 12;
  687.         MinID = 13;
  688.         MaxID = 14;
  689.     var
  690.         mylog: DialogPtr;
  691.         item, i: integer;
  692. begin
  693.     InitCursor;
  694.     mylog := GetNewDialog(140, nil, pointer(-1));
  695.     if not SumFrames then begin
  696.             ShowIntegratedValues := false;
  697.             FixIntegrationScale := false;
  698.         end;
  699.     SetDNum(MyLog, FramesID, FramesToAverage);
  700.     SetDialogItem(mylog, SumID, ord(SumFrames));
  701.     SetDialogItem(mylog, VideoRateID, ord(VideoRateAveraging));
  702.     SetDialogItem(mylog, ShowID, ord(ShowIntegratedValues));
  703.     SetDialogItem(mylog, FixID, ord(FixIntegrationScale));
  704.     SetDNum(MyLog, MinID, IntegrationMin);
  705.     SetDNum(MyLog, MaxID, IntegrationMax);
  706.     SelIText(MyLog, FramesID, 0, 32767);
  707.     repeat
  708.         ModalDialog(nil, item);
  709.         if item = FramesID then
  710.             FramesToAverage := GetDNum(MyLog, FramesID);
  711.         if item = SumID then begin
  712.                 SumFrames := not SumFrames;
  713.                 SetDialogItem(mylog, SumID, ord(SumFrames));
  714.             end;
  715.         if item = VideoRateID then begin
  716.                 VideoRateAveraging := not VideoRateAveraging;
  717.                 SetDialogItem(mylog, VideoRateID, ord(VideoRateAveraging));
  718.             end;
  719.         if item = ShowID then begin
  720.                 ShowIntegratedValues := not ShowIntegratedValues;
  721.                 SetDialogItem(mylog, ShowID, ord(ShowIntegratedValues));
  722.                 if ShowIntegratedValues then
  723.                     SumFrames := true;
  724.                 SetDialogItem(mylog, SumID, ord(SumFrames));
  725.             end;
  726.         if item = FixID then begin
  727.                 FixIntegrationScale := not FixIntegrationScale;
  728.                 SetDialogItem(mylog, FixID, ord(FixIntegrationScale));
  729.                 if FixIntegrationScale then
  730.                     SumFrames := true;
  731.                 SetDialogItem(mylog, SumID, ord(SumFrames));
  732.             end;
  733.         if (item = MinID) or (item = MaxID) then begin
  734.                 if item = MinID then
  735.                     IntegrationMin := GetDNum(MyLog, MinID)
  736.                 else
  737.                     IntegrationMax := GetDNum(MyLog, MaxID);
  738.                 SumFrames := true;
  739.                 SetDialogItem(mylog, SumID, ord(SumFrames));
  740.                 FixIntegrationScale := true;
  741.                 SetDialogItem(mylog, FixID, ord(FixIntegrationScale));
  742.             end;
  743.     until (item = ok) or (item = cancel);
  744.     DisposDialog(mylog);
  745.     if FramesToAverage < 2 then
  746.         FramesToAverage := 2;
  747.     if IntegrationMin < 0 then
  748.         IntegrationMin := 0;
  749.     if IntegrationMax > 32767 then
  750.         IntegrationMax := 32767;
  751.     if VideoRateAveraging and (item <> cancel) then begin
  752.             if FrameGrabber <> ScionLG3 then begin
  753.                     VideoRateAveraging := false;
  754.                     PutMessage('Video rate capture requires a Scion LG-3.');
  755.                     DoAveragingOptions := false;
  756.                     exit(DoAveragingOptions);
  757.                 end;
  758.             if FramesToAverage > MaxLG3Frames then begin
  759.                     FramesToAverage := MaxLG3Frames;
  760.                     DoAveragingOptions := false;
  761.                     PutMessage(concat('This ', long2str(MaxLG3Frames div 2), 'MB LG-3 can capture a maximum of ', long2str(MaxLG3Frames), ' frames at video rates.'));
  762.                     exit(DoAveragingOptions);
  763.                 end;
  764.         end;
  765.     DoAveragingOptions := item <> cancel;
  766. end;
  767.  
  768.  
  769. procedure AverageFrames;
  770.     type
  771.         IntPtr = ^integer;
  772.         SumLineType = array[0..2047] of integer;
  773.         sptr = ^SumLineType;
  774.     var
  775.         AutoSelectAll: boolean;
  776.         SelectionSize, FrameBufferSize, offset, StartTicks: LongInt;
  777.         SumBase, src, srcbase, dst, OffscreenBase: ptr;
  778.         str1, str2: str255;
  779.         xLines, xPixelsPerLine, BytesPerLine, frame, line, pixel: integer;
  780.         aline, BlankLine: LineType;
  781.         GrabRect: rect;
  782.         DisplayPoint: point;
  783.         hstart, vstart, wwidth, wheight: integer;
  784.         j, FramesAveraged: integer;
  785.         SrcRowBytes, DstRowBytes, i, value, MinV, MaxV, range, ActualMin, ActualMax: LongInt;
  786.         iptr: IntPtr;
  787.         FrameLine: LinePtr;
  788.         SumLine: sptr;
  789.         SaveBlankFieldInfo: InfoPtr;
  790.         myMMUMode: signedbyte;
  791. begin
  792.     with info^ do
  793.         if (PictureType <> FrameGrabberType) and (PictureType <> ScionType) then begin
  794.                 PutMessage('You must have an active Camera window(created using Start Capturing) in order to average frames.');
  795.                 macro := false;
  796.                 exit(AverageFrames)
  797.             end;
  798.     if NotRectangular or NotinBounds then begin
  799.             macro := false;
  800.             exit(AverageFrames);
  801.         end;
  802.     if (not OptionKeyWasDown) and (not macro) then begin
  803.             if not DoAveragingOptions then
  804.                 exit(AverageFrames);
  805.         end;
  806.     SaveBlankFieldInfo := BlankFieldInfo;
  807.     BlankFieldInfo := nil; {We don't want to do shading correction now}
  808.     StopDigitizing;
  809.     BlankFieldInfo := SaveBlankFieldInfo;
  810.     OptionKeyWasDown := false;
  811.     DrawLabels('Frame:', 'Total:', '');
  812.     ShowTriggerMessage;
  813.     ShowWatch;
  814.     AutoSelectAll := not Info^.RoiShowing;
  815.     if AutoSelectAll then
  816.         SelectAll(false);
  817.     with info^.RoiRect do
  818.         SelectionSize := (LongInt(right) - left) * (bottom - top);
  819.     FrameBufferSize := SelectionSize * 2;
  820.     if FrameBufferSize > BigBufSize then begin
  821.             NumToString(FrameBufferSize div 1024, str1);
  822.             NumToString(BigBufSize div 1024, str2);
  823.             str2 := concat(str1, 'K bytes are required, but only ', str2, 'K bytes are available.');
  824.             PutMessage(concat('There is not enough memory to do the requested frame averaging. ', str2));
  825.             if AutoSelectAll or (BlankFieldInfo <> nil) then
  826.                 KillRoi
  827.             else
  828.                 ShowRoi;
  829.             exit(AverageFrames)
  830.         end;
  831.     WhatToUndo := NothingToUndo;
  832.     WhatsOnClip := NothingOnClip;
  833.     SumBase := BigBuf;
  834.     case FrameGrabber of
  835.         QuickCapture:  begin
  836.                 ContinuousHistogram := false;
  837.                 ResetQuickCapture
  838.             end;
  839.         ScionLG3:  begin
  840.                 ContinuousHistogram := false;
  841.                 ResetScionLG3
  842.             end;
  843.         Scion:  begin
  844.                 with info^.wrect do begin
  845.                         wwidth := right;
  846.                         wheight := bottom;
  847.                     end;
  848.                 hstart := (640 - wwidth) div 2;
  849.                 vstart := (480 - wheight) div 2;
  850.                 SetRect(GrabRect, hstart, vstart, hstart + wwidth, vstart + wheight);
  851.                 with DisplayPoint do begin
  852.                         h := PicLeftBase;
  853.                         v := PicTopBase;
  854.                     end;
  855.                 ResetScion(GrabRect, DisplayPoint);
  856.                 HideCursor;
  857.             end;
  858.     end; {case}
  859.     with info^, info^.RoiRect do begin
  860.             offset := left + LongInt(top) * BytesPerRow;
  861.             OffscreenBase := ptr(ord4(PicBaseAddr) + offset);
  862.             if FrameGrabber = Scion then
  863.                 with DisplayPoint do begin
  864.                         BringToFront(wptr);
  865.                         offset := left + h + (v + top) * ScreenRowBytes;
  866.                         srcbase := ptr(ord4(ScreenBase) + offset);
  867.                         SrcRowBytes := ScreenRowBytes;
  868.                     end
  869.             else begin
  870.                     offset := left + LongInt(top) * fgRowBytes;
  871.                     srcbase := ptr(ord4(ptr(fgSlotBase)) + offset);
  872.                     SrcRowBytes := fgRowBytes;
  873.                 end;
  874.             xLines := bottom - top;
  875.             xPixelsPerLine := right - left;
  876.             BytesPerLine := xPixelsPerLine * 2;
  877.         end; {with}
  878.     for i := 0 to BytesPerLine - 1 do
  879.         BlankLine[i] := WhiteIndex;
  880.     dst := SumBase;
  881.     for line := 1 to xLines do begin {zero buffer}
  882.             BlockMove(@BlankLine, dst, BytesPerLine);
  883.             dst := ptr(ord4(dst) + BytesPerLine);
  884.         end;
  885.     info^.title := 'Camera';
  886.     UpdateTitleBar;
  887.     StartTicks := TickCount;
  888.     if FrameGrabber <> ScionLG3 then
  889.         VideoRateAveraging := false;
  890.     if VideoRateAveraging then begin
  891.             if FramesToAverage > MaxLG3Frames then
  892.                 FramesToAverage := MaxLG3Frames;
  893.             ExternalTrigger := false;
  894.             BufferReg^ := 0;
  895.             GetFrame;
  896.             StartTicks := TickCount - 2;
  897.             for frame := 1 to FramesToAverage - 1 do begin
  898.                     BufferReg^ := Frame;
  899.                     GetFrame;
  900.                 end;
  901.             BufferReg^ := 0;
  902.             RealToString((TickCount - StartTicks) / 60.0, 1, 2, str1);
  903.             ShowFrameRate(concat(Long2str(FramesToAverage), ' frames', cr, str1, ' seconds', cr), StartTicks, FramesToAverage);
  904.         end;
  905.     for frame := 0 to FramesToAverage - 1 do begin
  906.             Show2Values(frame + 1, FramesToAverage);
  907.             if VideoRateAveraging then
  908.                 BufferReg^ := Frame
  909.             else begin
  910.                     if FrameGrabber = Scion then
  911.                         GetScionFrame(DisplayPoint)
  912.                     else
  913.                         GetFrame;
  914.                 end;
  915.             src := srcbase;
  916.             dst := SumBase;
  917.             myMMUMode := 1;
  918.             SwapMMUMode(myMMUMode);
  919.             for line := 1 to xLines do begin
  920.                     AddLineToSum(src, dst, xPixelsPerLine);
  921.                     src := ptr(ord4(src) + SrcRowBytes);
  922.                     dst := ptr(ord4(dst) + BytesPerLine);
  923.                 end;
  924.             SwapMMUMode(myMMUMode);
  925.             if FrameGrabber <> Scion then
  926.                 UpdateScreen(info^.RoiRect);
  927.             if CommandPeriod then begin
  928.                     beep;
  929.                     if AutoSelectAll then
  930.                         KillRoi
  931.                     else
  932.                         ShowRoi;
  933.                     exit(AverageFrames);
  934.                 end;
  935.         end; {for}
  936.     src := SumBase;
  937.     dst := OffscreenBase;
  938.     DstRowBytes := info^.BytesPerRow;
  939.     if SumFrames then begin
  940.             MinV := 2000000000;
  941.             MaxV := 0;
  942.             iptr := IntPtr(src);
  943.             for i := 1 to SelectionSize do begin
  944.                     value := iptr^;
  945.                     if value > MaxV then
  946.                         MaxV := value;
  947.                     if value < MinV then
  948.                         MinV := value;
  949.                     iptr := IntPtr(ord4(iptr) + 2);
  950.                 end;
  951.             ActualMin := MinV;
  952.             ActualMax := MaxV;
  953.             if FixIntegrationScale then begin
  954.                     MinV := IntegrationMin;
  955.                     MaxV := IntegrationMax;
  956.                 end;
  957.             range := MaxV - MinV;
  958.             if range <> 0 then
  959.                 for line := 1 to xLines do begin
  960.                         SumLine := sptr(src);
  961.                         FrameLine := LinePtr(dst);
  962.                         for j := 0 to xPixelsPerLine - 1 do begin
  963.                                 value := LongInt(SumLine^[j] - MinV) * 253 div range + 1;
  964.                                 if value < 0 then
  965.                                     value := 0;
  966.                                 if value > 255 then
  967.                                     value := 255;
  968.                                 FrameLine^[j] := value;
  969.                             end;
  970.                         src := ptr(ord4(src) + BytesPerLine);
  971.                         dst := ptr(ord4(dst) + DstRowBytes);
  972.                     end
  973.             else
  974.                 beep;
  975.         end
  976.     else
  977.         for line := 1 to xLines do begin
  978.                 SumLine := sptr(src);
  979.                 FrameLine := LinePtr(dst);
  980.                 for j := 0 to xPixelsPerLine - 1 do
  981.                     FrameLine^[j] := SumLine^[j] div FramesToAverage;
  982.                 src := ptr(ord4(src) + BytesPerLine);
  983.                 dst := ptr(ord4(dst) + DstRowBytes);
  984.             end;
  985.     if not VideoRateAveraging then begin
  986.             if SumFrames then begin
  987.                     if FixIntegrationScale then
  988.                         str1 := concat('min=', long2str(MinV), ' (', long2str(ActualMin), ')', cr, 'max=', long2str(MaxV), ' (', long2str(ActualMax), ')', cr)
  989.                     else
  990.                         str1 := concat('min=', long2str(MinV), cr, 'max=', long2str(MaxV), cr)
  991.                 end
  992.             else
  993.                 str1 := '';
  994.             RealToString((TickCount - StartTicks) / 60.0, 1, 2, str2);
  995.             ShowFrameRate(concat(Long2str(FramesToAverage), ' frames', cr, str1, str2, ' seconds', cr), StartTicks, FramesToAverage);
  996.         end;
  997.     UpdatePicWindow;
  998.     if AutoSelectAll then
  999.         KillRoi
  1000.     else
  1001.         ShowRoi;
  1002.     if BlankFieldInfo <> nil then
  1003.         CorrectShading;
  1004.     if ShowIntegratedValues then
  1005.         with info^ do begin
  1006.                 DensityCalibrated := true;
  1007.                 fit := StraightLine;
  1008.                 nCoefficients := 2;
  1009.                 coefficient[2] := (MaxV - MinV) / 253.0;
  1010.                 coefficient[1] := MinV - coefficient[2];
  1011.                 ZeroClip := false;
  1012.                 UpdateTitleBar;
  1013.                 if macro then
  1014.                     GenerateValues;
  1015.             end
  1016. end;
  1017.  
  1018.  
  1019. function GetFGPixel (h, v: integer): integer;
  1020.     var
  1021.         offset: LongInt;
  1022.         p: ptr;
  1023. begin
  1024.     with Info^ do begin
  1025.             if (h < 0) or (v < 0) or (h >= fgWidth) or (v >= fgHeight) then begin
  1026.                     GetFGPixel := WhiteIndex;
  1027.                     exit(GetFGPixel);
  1028.                 end;
  1029.             offset := LongInt(v) * fgRowBytes + h;
  1030.             if offset >= LongInt(fgHeight) * fgRowBytes then begin
  1031.                     GetFGPixel := WhiteIndex;
  1032.                     exit(GetFGPixel);
  1033.                 end;
  1034.             p := ptr(ord4(ptr(fgSlotBase)) + offset);
  1035.             GetFGPixel := BAND(p^, 255);
  1036.         end;
  1037. end;
  1038.  
  1039.  
  1040. procedure WaitForTrigger;
  1041. begin
  1042.     StopDigitizing;
  1043.     ShowWatch;
  1044.     case FrameGrabber of
  1045.         QuickCapture:  begin
  1046.                 ControlReg^ := BitAnd($82, 255);  {Wait for external trigger and capture one frame}
  1047.                 repeat
  1048.                 until (ControlReg^ >= 0) or Button;  {Wait for it to complete}
  1049.             end;
  1050.         ScionLG3:  begin
  1051.                 ControlReg^ := $90; {Wait for external trigger and capture one frame}
  1052.                 repeat
  1053.                 until (BitAnd(ControlReg^, $80) = $80) or Button;  {Wait for it to complete}
  1054.             end;
  1055.         otherwise
  1056.             repeat
  1057.             until Button;
  1058.     end;
  1059. end;
  1060.  
  1061.  
  1062. procedure SetOffset (var offset, gain: integer);
  1063. begin
  1064.     if offset < 0 then
  1065.         offset := 0;
  1066.     if offset > 255 then
  1067.         offset := 255;
  1068.     if offset > gain then
  1069.         offset := gain;
  1070.     LG3DacLow := offset;
  1071.     LG3DacHigh := LG3DacLow + (255 - gain);
  1072. end;
  1073.  
  1074.  
  1075. procedure SetGain (var offset, gain: integer);
  1076. begin
  1077.     if gain < 0 then
  1078.         gain := 0;
  1079.     if gain > 255 then
  1080.         gain := 255;
  1081.     if gain < LG3DacLow then
  1082.         gain := LG3DacLow;
  1083.     LG3DacHigh := LG3DacLow + (255 - gain);
  1084. end;
  1085.  
  1086.  
  1087. procedure ShowChannel;
  1088. begin
  1089.     SetDialogItem(VideoControl, FirstChannelID, ord(VideoChannel = 0));
  1090.     SetDialogItem(VideoControl, FirstChannelID + 1, ord(VideoChannel = 1));
  1091.     SetDialogItem(VideoControl, FirstChannelID + 2, ord(VideoChannel = 2));
  1092.     SetDialogItem(VideoControl, FirstChannelID + 3, ord(VideoChannel = 3));
  1093. end;
  1094.  
  1095.  
  1096. procedure UpdateVideoControl;
  1097. begin
  1098.     if VideoControl <> nil then
  1099.         SetDialogItem(VideoControl, TriggerID, ord(ExternalTrigger));
  1100. end;
  1101.  
  1102.  
  1103. procedure ShowOffsetAndGain (offset, gain: integer);
  1104.     var
  1105.         str: str255;
  1106. begin
  1107.     RealToString(offset, 3, 0, str);
  1108.     if str[1] = ' ' then
  1109.         str[1] := '0';
  1110.     if str[2] = ' ' then
  1111.         str[2] := '0';
  1112.     SetDString(VideoControl, OffsetID, str);
  1113.     RealToString(gain, 3, 0, str);
  1114.     if str[1] = ' ' then
  1115.         str[1] := '0';
  1116.     if str[2] = ' ' then
  1117.         str[2] := '0';
  1118.     SetDString(VideoControl, GainID, str);
  1119. end;
  1120.  
  1121.  
  1122. procedure ShowVideoControl;
  1123.     var
  1124.         gain: integer;
  1125. begin
  1126.     InitCursor;
  1127.     VideoControl := GetNewDialog(130, nil, pointer(-1));
  1128.     ShowChannel;
  1129.     SetDialogItem(VideoControl, InvertID, ord(InvertVideo));
  1130.     SetDialogItem(VideoControl, HighlightID, ord(HighlightSaturatedPixels));
  1131.     SetDialogItem(VideoControl, OscillatingID, ord(OscillatingMovies));
  1132.     SetDialogItem(VideoControl, TriggerID, ord(ExternalTrigger));
  1133.     SetDialogItem(VideoControl, BlindID, ord(BlindMovieCapture));
  1134.     SetDialogItem(VideoControl, SyncID, ord(SyncMode = SeparateSync));
  1135.     gain := 255 - (LG3DacHigh - LG3DacLow);
  1136.     ShowOffsetAndGain(LG3DacLow, gain);
  1137. end;
  1138.  
  1139.  
  1140. procedure DoVideoControl (item: integer);
  1141.     var
  1142.         i: integer;
  1143.         OutOfRange, WasDigitizing: boolean;
  1144.         offset, gain, inc, count: integer;
  1145.  
  1146.     procedure CheckFrameGrabber;
  1147.     begin
  1148.         if FrameGrabber <> ScionLG3 then begin
  1149.                 PutMessage('Programmable offset and gain are only supported on the Scion LG-3.');
  1150.                 exit(DoVideoControl);
  1151.             end;
  1152.     end;
  1153.  
  1154.     procedure SetVideoItem (item, value: integer);
  1155.     begin
  1156.         if VideoControl <> nil then
  1157.             SetDialogItem(VideoControl, item, value);
  1158.     end;
  1159.  
  1160. begin
  1161.     InitCursor;
  1162.     gain := 255 - (LG3DacHigh - LG3DacLow);
  1163.     if (item >= FirstChannelID) and (item <= (FirstChannelID + 3)) then begin
  1164.             VideoChannel := item - FirstChannelID;
  1165.             if VideoControl <> nil then
  1166.                 ShowChannel;
  1167.             if digitizing then
  1168.                 ResetFrameGrabber;
  1169.         end;
  1170.     if item = InvertID then begin
  1171.             InvertVideo := not InvertVideo;
  1172.             SetVideoItem(InvertID, ord(InvertVideo));
  1173.             if digitizing then
  1174.                 ResetFrameGrabber;
  1175.         end;
  1176.     if item = HighlightID then begin
  1177.             HighlightSaturatedPixels := not HighlightSaturatedPixels;
  1178.             SetVideoItem(HighlightID, ord(HighlightSaturatedPixels));
  1179.             if digitizing then begin
  1180.                     if HighlightSaturatedPixels then
  1181.                         HighlightPixels
  1182.                     else
  1183.                         LoadLUT(info^.ctable);
  1184.                 end;
  1185.         end;
  1186.     if item = OscillatingID then begin
  1187.             OscillatingMovies := not OscillatingMovies;
  1188.             SetVideoItem(OscillatingID, ord(OscillatingMovies));
  1189.         end;
  1190.     if item = TriggerID then begin
  1191.             ExternalTrigger := not ExternalTrigger;
  1192.             case FrameGrabber of
  1193.                 QuickCapture, ScionLG3:  begin
  1194.                         WasDigitizing := digitizing;
  1195.                         StopDigitizing;
  1196.                         if ExternalTrigger and WasDigitizing then
  1197.                             StartDigitizing;
  1198.                     end;
  1199.                 otherwise
  1200.                     ExternalTrigger := false;
  1201.             end;
  1202.             SetVideoItem(TriggerID, ord(ExternalTrigger));
  1203.         end;
  1204.     if item = BlindID then begin
  1205.             BlindMovieCapture := not BlindMovieCapture;
  1206.             SetVideoItem(BlindID, ord(BlindMovieCapture));
  1207.         end;
  1208.     if item = SyncID then begin
  1209.             if SyncMode <> SeparateSync then
  1210.                 SyncMode := SeparateSync
  1211.             else
  1212.                 SyncMode := NormalSync;
  1213.             case FrameGrabber of
  1214.                 ScionLG3: 
  1215.                     if digitizing then
  1216.                         ResetFrameGrabber;
  1217.                 QuickCapture:  begin
  1218.                         PutMessage('Sync is not under program control on the QuickCapure card.');
  1219.                         SyncMode := NormalSync;
  1220.                         macro := false;
  1221.                     end;
  1222.                 otherwise
  1223.                     ;
  1224.             end;
  1225.             SetVideoItem(SyncID, ord(SyncMode = SeparateSync));
  1226.         end;
  1227.     if (item >= OffsetUpID) and (item <= GainDownID) then begin
  1228.             CheckFrameGrabber;
  1229.             offset := LG3DacLow;
  1230.             inc := 1;
  1231.             count := 0;
  1232.             repeat
  1233.                 count := count + 1;
  1234.                 if count > 2 then
  1235.                     inc := 2;
  1236.                 if count > 4 then
  1237.                     inc := 5;
  1238.                 if count > 8 then
  1239.                     inc := 10;
  1240.                 case item of
  1241.                     OffsetUpID:  begin
  1242.                             offset := offset + inc;
  1243.                             SetOffset(offset, gain);
  1244.                         end;
  1245.                     OffsetDownID:  begin
  1246.                             offset := offset - inc;
  1247.                             SetOffset(offset, gain);
  1248.                         end;
  1249.                     GainUpID:  begin
  1250.                             gain := gain + inc;
  1251.                             SetGain(offset, gain);
  1252.                         end;
  1253.                     GainDownID:  begin
  1254.                             gain := gain - inc;
  1255.                             SetGain(offset, gain);
  1256.                         end;
  1257.                 end; {case}
  1258.                 ShowOffsetAndGain(LG3DacLow, gain);
  1259.                 if Digitizing and (count > 1) then begin
  1260.                         DacLowReg^ := LG3DacLow;
  1261.                         DacHighReg^ := LG3DacHigh;
  1262.                         CaptureAndDisplayFrame;
  1263.                         if ContinuousHistogram then begin
  1264.                                 ShowContinuousHistogram;
  1265.                                 DrawHistogram
  1266.                             end
  1267.                     end
  1268.                 else
  1269.                     wait(5);
  1270.             until not button;
  1271.         end;
  1272.     if item = ResetID then begin
  1273.             CheckFrameGrabber;
  1274.             LG3DacLow := DefaultLG3DacLow;
  1275.             LG3DacHigh := DefaultLG3DacHigh;
  1276.             gain := 255 - (LG3DacHigh - LG3DacLow);
  1277.             ParamText(long2str(LG3DacLow), long2str(gain), '', '');
  1278.             ShowOffsetAndGain(LG3DacLow, gain);
  1279.         end;
  1280.     if FramesToAverage < 2 then
  1281.         FramesToAverage := 2;
  1282.     if (FrameGrabber = Scion) and (ExternalTrigger or BlindMovieCapture) then begin
  1283.             PutMessage('External triggering and blind movie capture are not supported with the SCION frame grabber card.');
  1284.             ExternalTrigger := false;
  1285.             BlindMovieCapture := false;
  1286.         end;
  1287.     if FrameGrabber = ScionLG3 then begin
  1288.             DacLowReg^ := LG3DacLow;
  1289.             DacHighReg^ := LG3DacHigh;
  1290.         end;
  1291. end;
  1292.  
  1293.  
  1294. end.